#ifndef __timer_H__
#define __timer_H__

#include <functional>
#include <memory.h>
#include <memory>
#include <type_traits>
#include <vector>
#include <set>
#include "thread.h"

namespace framework
{
class TimerManager;

//定时器
class Timer: public std::enable_shared_from_this<Timer>
{
    friend class TimerManager;
public:
    using ptr = std::shared_ptr<Timer>;

    //取消定时器
    bool cancel();

    //刷新设置定时器的执行时间
    bool refresh();

    //重置定时器时间
    //ms 定时器执行时间间隔（毫秒）
    //from_now 是否从当前时间开始计算
    bool reset(uint64_t ms, bool from_now);

private:
    //构造函数，写在private中，只能通过TimerManager类来构造Timer
    //ms: 定时器执行时间间隔
    //cb: 回调函数
    //recurring: 是否循环
    //manager: 定时器管理器
    Timer(bool recurring, uint64_t ms, TimerManager* manager, std::function<void()> cb);

    //构造函数
    //next 执行的时间戳（毫秒）
    Timer(uint64_t next);

    //定时器比较仿函数
    struct Comparator
    {
        //比较定时器的智能指针的大小 按照定时器的执行时间比较
        bool operator()(const Timer::ptr& lhs, const Timer::ptr& rhs) const;
    };

    bool m_recurring        = true;    //是否为循环定时器
    uint64_t m_ms           = 0;       //执行周期
    uint64_t m_next         = 0;       //精确的执行时间
    TimerManager* m_manager = nullptr; //定时器管理器
    std::function<void()> m_cb;     //回调函数
};



//定时器管理器
class TimerManager
{
    friend class Timer;
public:
    //读写锁类型
    using RWMutexType = RWMutex;

    TimerManager();

    virtual ~TimerManager();

    //添加定时器
    //ms 定时器执行的时间间隔
    //cb 定时器回调函数
    //recurring 是否循环定时器
    Timer::ptr addTimer(uint64_t ms, std::function<void()> cb, bool recurring = false);

    //添加条件定时器
    //ms 定时器执行的时间间隔
    //cb 定时器回调函数
    //weak_cond 条件
    //recurring 是否循环定时器
    Timer::ptr addConditionTimer(uint64_t ms, std::function<void()> cb,  std::weak_ptr<void> weak_cond, bool recurring = false);

    //返回到最近一个定时器执行的时间间隔（毫秒）
    uint64_t getNextTimer();

    //获取需要执行的定时器回调函数列表
    //cbs 回调函数数组
    void listExpiredCb(std::vector<std::function<void()>>& cbs);

    //是否有定时器
    bool hasTimer();

protected:
    //当有新的定时器插入到定时器的首部，执行该函数
    virtual void onTimerInsertedAtFront() = 0;

    //将定时器添加到管理器中
    void addTimer(Timer::ptr val, RWMutexType::WriteLock& lock);

private:

    //检测服务器时间是否被调后了
    bool detectClockRollover(uint64_t now_ms);


    RWMutexType m_mutex;                  //读写锁
    bool        m_tickled       = false;  //是否触发onTimerInsertedAtFront
    uint64_t    m_previouseTime = 0;      //上次执行时间
    std::set<Timer::ptr, Timer::Comparator> m_timers;  //定时器集合
};

}




#endif
